using System;
using System.Collections.Generic;
using System.Text;

using NSimpleDB.Service.Contract;

namespace NSimpleDB.Service.VistaDb.Resultsets
{
    internal class ResultsetBuffer
    {
        private readonly TimeSpan maxResultsetLifetime = new TimeSpan(0, 0, 0, 2);

        private Dictionary<string, Resultset> resultsets;
        private DateTime lastGCRunAt;


        public ResultsetBuffer()
        {
            this.resultsets = new Dictionary<string, Resultset>();
            this.lastGCRunAt = DateTime.Now;
        }


        public string AddResultset(IList<string> resultsetEntries)
        {
            this.GarbageCollectResultsets();

            if (resultsetEntries.Count > 0)
            {
                lock (this.resultsets)
                {
                    Resultset rs = new Resultset(resultsetEntries);
                    this.resultsets.Add(rs.Token, rs);
                    return rs.Token;
                }
            }
            else
                return null;
        }


        public string[] GetNextResultsetPage(int maxNumberOfEntries, ref string token)
        {
            if (token != null && token != "")
            {
                lock (this.resultsets)
                {
                    Resultset rs;
                    if (this.resultsets.TryGetValue(token, out rs))
                    {
                        string[] entries = rs.GetNextPage(maxNumberOfEntries);
                        if (rs.Count == 0) token = null;
                        return entries;
                    }
                    else
                    {
                        token = null;
                        return new string[] { };
                    }
                }
            }
            else
            {
                token = null;
                return new string[] { };
            }
        }


        private void GarbageCollectResultsets()
        {
            lock (this.resultsets)
            {
                if (DateTime.Now.Subtract(this.lastGCRunAt) > this.maxResultsetLifetime)
                {
                    List<string> pageTokens = new List<string>(this.resultsets.Keys);
                    foreach (string token in pageTokens)
                    {
                        Resultset rs = this.resultsets[token];
                        if (DateTime.Now.Subtract(rs.CreatedAt) > this.maxResultsetLifetime)
                            this.resultsets.Remove(token);
                    }

                    this.lastGCRunAt = DateTime.Now;
                }
            }
        }
    }
}
